home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_asm / 68kdis / libmtch.c < prev    next >
C/C++ Source or Header  |  1988-12-02  |  7KB  |  309 lines

  1. /*
  2.  *    SCCS:    @(#)libmtch.c    1.2    11/2/84    14:18:55
  3.  *    Read library files.
  4.  *
  5.  ***********************************************************************
  6.  *    This software is copyright of
  7.  *
  8.  *        John M Collins
  9.  *        47 Cedarwood Drive
  10.  *        St Albans
  11.  *        Herts, AL4 0DN
  12.  *        England            +44 727 57267
  13.  *
  14.  *    and is released into the public domain on the following conditions:
  15.  *
  16.  *        1.  No free maintenance will be guaranteed.
  17.  *        2.  Nothing may be based on this software without
  18.  *            acknowledgement, including incorporation of this
  19.  *            notice.
  20.  *
  21.  *    Notwithstanding the above, the author welcomes correspondence and bug
  22.  *    fixes.
  23.  ***********************************************************************
  24.  */
  25.  
  26. #include <stdio.h>
  27. #include <fcntl.h>
  28. #include <string.h>
  29. #include <a.out.h>
  30. #include <ar.h>
  31. #include <setjmp.h>
  32. #include <ldfcn.h>
  33. #include "unc.h"
  34.  
  35. long    atol();
  36. long    lseek();
  37. void    bfopen(), bfclose(), nomem();
  38. void    rrell2(), markmatch();
  39. char    *malloc();
  40. int    matchup();
  41. long    findstart();
  42.  
  43. char    verbose;        /*  Tell the world what we are doing  */
  44. char    *tfnam;
  45. char    *cfile;
  46. ef_fids    mainfile;
  47. struct    commit    dreltab;
  48. int    donedrel, donebrel;
  49. long    trelpos, drelpos, brelpos;
  50. static    struct    libit    currlib = {NULL, NULL, ""};
  51.  
  52. void    lclash(str)
  53. char    *str;
  54. {
  55.     (void) fprintf(stderr, "Library scan failure - %s\n", str);
  56.     (void) fprintf(stderr, "Searching %s\n", cfile);
  57.     if  (currlib.lf_name[0])
  58.         (void) fprintf(stderr, "Member is %s\n", currlib.lf_name);
  59.     exit(255);
  60. }
  61.  
  62. /*
  63.  *    Find next member.
  64.  */
  65.  
  66. long    nextmemb(filename,lfd)
  67. char *filename;
  68. register  struct  libit     *lfd;
  69. {
  70.     struct    ar_hdr    arbuf;
  71.     
  72.     ldaclose(lfd->ldptr2);
  73.     if (ldclose(lfd->ldptr != FAILURE))    /* end of archive */
  74.         return -1;
  75.     lfd->ldptr = ldopen(filename,lfd->ldptr);
  76.     ldahread(lfd->ldptr, (char *)&arbuf);
  77.     (void) strncpy(lfd->lf_name, arbuf.ar_name, sizeof(lfd->lf_name));
  78.     return 1;
  79. }
  80.  
  81. /*
  82.  *    Decode a file name thus -
  83.  *
  84.  *    -lxxx decode as /lib/libxxx.a /usr/lib/libxxx.a etc
  85.  *    -Lxxx forget "lib" ".a" bit thus -Lcrt0.o
  86.  *    or read LDPATH environment var to give list of directories as sh
  87.  *    (default /lib:/usr/lib).
  88.  *
  89.  *    Alternatively treat as normal pathname.
  90.  *
  91.  *    File names may be followed by (membername) if the file is an archive,
  92.  *    thus
  93.  *
  94.  *        -lc(printf.o)
  95.  *
  96.  *    in which case the specified module is fetched.
  97.  */
  98.  
  99. struct    libit    *getfnam(str)
  100. char    *str;    /* will be expanded to full path name if necessary */
  101. {
  102.     char    *bp, *ep = NULL, *pathb, *pathe, *fullpath = NULL;
  103.     static    char    *pathn;
  104.     extern    char    *getenv();
  105.      char    magic[8];
  106.     struct    ar_hdr    arhdr;
  107.     LDFILE *ldptr;
  108.  
  109.      if  ((bp = strrchr(str, '(')) != NULL &&
  110.           (ep = strrchr(str, ')')) != NULL)
  111.         *ep = *bp = '\0';
  112.  
  113.     if  (str[0] == '-'  &&  (str[1] == 'l' || str[1] == 'L'))  {
  114.         if  (pathn == NULL)  {
  115.             if  ((pathn = getenv("LDPATH")) == NULL)
  116.                 pathn = "/lib:/usr/lib";
  117.         }
  118.         fullpath = malloc((unsigned)(strlen(pathn) + strlen(str) + 1));
  119.         if  (fullpath == NULL)
  120.             nomem();
  121.         pathb = pathn;
  122.         do  {
  123.              pathe = strchr(pathb, ':');
  124.             if  (*pathb == ':')
  125.                 fullpath[0] = '\0';
  126.             else  {
  127.                 if  (pathe != NULL)
  128.                     *pathe = '\0';
  129.                 (void) strcpy(fullpath, pathb);
  130.                 (void) strcat(fullpath, "/");
  131.                 if  (pathe != NULL)
  132.                     *pathe = ':';
  133.             }
  134.             if  (str[1] == 'l')
  135.                 (void) strcat(fullpath, "lib");
  136.             (void) strcat(fullpath, &str[2]);
  137.             if  (str[1] == 'l')
  138.                 (void) strcat(fullpath, ".a");
  139.             if  ((ldptr = ldopen(fullpath, NULL)) != NULL)
  140.                 goto  found;
  141.             pathb = pathe + 1;
  142.         }   while  (pathe != NULL);
  143.         
  144.         (void) fprintf(stderr, "Unable to locate lib%s.a in %s\n",
  145.             &str[2], pathn);
  146.         exit(101);
  147.     }
  148.     else  if  ((ldptr = ldopen(str, NULL)) == NULL)  {
  149.         (void) fprintf(stderr, "Cannot open %s\n", str);
  150.         exit(102);
  151.     }
  152.     
  153. found:
  154.  
  155.     str = fullpath? fullpath: str;
  156.      if  (FREAD(magic, sizeof(magic),1,ldptr) != 1  ||
  157.          strcmp(magic, ARMAG) != 0)  {
  158.         if  (ep != NULL)  {
  159.             (void) fprintf(stderr, "%s is not library file\n", str);
  160.             exit(103);
  161.         }
  162.         currlib.ldptr = ldptr;
  163.         currlib.ldptr2 = ldaopen(str,ldptr);
  164.         currlib.lf_name[0] = '\0';
  165.         return  &currlib;
  166.     }
  167.     
  168.     /*
  169.      *    It appears to be a library file - see if we want a specific
  170.      *    one.
  171.      */
  172.     
  173.     if  (ep != NULL)  {
  174.          char *cp;
  175.  
  176.         for  (;;)  {
  177.             if  (ldahread(ldptr,&arhdr) == FAILURE)  {
  178.                 (void) fprintf(stderr, "Cannot find member %s in %s\n",
  179.                     bp+1, str);
  180.                 exit(103);
  181.             }
  182.              for ( cp = arhdr.ar_name + sizeof(arhdr.ar_name) - 1;
  183.                  *cp == ' ';
  184.                  cp -- ) ;
  185.              if  (strncmp(bp+1, arhdr.ar_name, cp - arhdr.ar_name + 1) == 0)
  186.                 break;
  187.  
  188.             if (ldclose(ldptr) != FAILURE) {
  189.                 (void) fprintf(stderr, "Cannot find member %s in %s\n",
  190.                     bp+1, str);
  191.                 exit(103);
  192.             }
  193.             ldptr = ldopen(str,ldptr);
  194.         }
  195.         currlib.ldptr = ldptr;
  196.         currlib.ldptr2 = ldaopen(str,ldptr);
  197.         currlib.lf_name[0] = '\0';
  198.         *bp = '(';
  199.         *ep = ')';
  200.         return    &currlib;
  201.     }
  202.     
  203.     /*
  204.      *    Otherwise point to 1st member in library.
  205.      */
  206.     
  207.     if  (ldahread(ldptr, &arhdr) == FAILURE)  {
  208.         (void) fprintf(stderr, "Library %s empty\n", str);
  209.         exit(104);
  210.     }
  211.     currlib.ldptr = ldptr;
  212.     currlib.ldptr2 = ldaopen(str,ldptr);
  213.     (void) strncpy(currlib.lf_name, arhdr.ar_name, sizeof(currlib.lf_name));
  214.     return    &currlib;
  215. }
  216.  
  217. /*
  218.  *    Process library files.
  219.  */
  220.  
  221. #define    MINTEXT    6
  222.  
  223. void    lscan(nfiles, fnames)
  224. int    nfiles;
  225. char    **fnames;
  226. {
  227.     ef_fids    libfile;
  228.     register  ef_fid  ll = &libfile;
  229.     register  struct  libit     *clf;
  230.     extern    symbol    dolsymb();
  231.     int    firstfile;
  232.     
  233.     for  (;  nfiles > 0;  fnames++, nfiles--)  {
  234.         clf = getfnam(*fnames);
  235.         cfile = *fnames;
  236.         firstfile = 1;
  237.         do  {
  238.             bfopen(tfnam, ll);
  239.  
  240.             /*
  241.              *    If file is garbled, silently forget it and go
  242.              *    on to the next one.
  243.              */
  244.  
  245.             if  (!rtext(clf->ldptr, ll))
  246.                 goto  closeit;
  247.                 
  248.             if  (ll->ef_tsize < MINTEXT)
  249.                 goto  closeit;
  250.                 
  251.             if  (!rdata(clf->ldptr, ll))
  252.                 goto  closeit;
  253.                 
  254.             if  (rrell1(clf->ldptr, ll) < 0)
  255.                 goto  closeit;
  256.                 
  257.             /*
  258.              *    If first file in library, find it from
  259.              *    beginning of main file.
  260.              */
  261.             
  262.             if  (firstfile)  {
  263.                 if  ((trelpos = findstart(&mainfile, ll)) < 0)
  264.                     goto  closeit;
  265.                 firstfile = 0;
  266.             }
  267.             else   if  (!matchup(&mainfile, ll, trelpos))
  268.                     goto  closeit;
  269.             
  270.             /*
  271.              *    Found a match.
  272.              */
  273.             
  274.             if  (!rsymb(clf->ldptr, dolsymb, ll))  {
  275.                 (void) fprintf(stderr, "Corrupt file %s\n",
  276.                             *fnames);
  277.                 exit(150);
  278.             }
  279.             
  280.             donedrel = 0;
  281.             donebrel = 0;
  282.             rrell2(clf->ldptr, clf->ldptr2, ll);
  283.             if  (verbose)  {
  284.                 (void) fprintf(stderr, "Found: ");
  285.                 if  (clf->lf_name[0])
  286.                     (void) fprintf(stderr, "%.14s in ",
  287.                             clf->lf_name);
  288.                 (void) fprintf(stderr, "%s\n", *fnames);
  289.             }
  290.             if  (libfile.ef_stvec != NULL)  {
  291.                 free(libfile.ef_stvec);
  292.                 libfile.ef_stvec = NULL;
  293.                 libfile.ef_stcnt = 0;
  294.             }
  295.             dreltab.c_int = 0;
  296.                 
  297.             /*
  298.              *    Start looking next time round
  299.              *    where last one left off.
  300.              */
  301.             
  302.             markmatch(&mainfile, ll, trelpos);
  303.             trelpos += libfile.ef_tsize;
  304. closeit:
  305.             bfclose(ll);
  306.         }  while  (nextmemb(cfile,clf) >= 0);
  307.     }
  308. }
  309.